#include "../include/HPLCPacketManager.h"

#include "../../../include/HPLCData.h"

#include "../../../include/json.hpp"
#include "../../../src/common/include/Base64.hpp"
#include "../../../src/common/include/common.h"
#include "../../logger/include/CLogger.h"

using json = nlohmann::json;

template<typename T>
void json_to_obj(const json& j, std::string field, T& obj){
    if (field.empty()){
        return;
    }
    if (j.contains(field)){
        j.at(field).get_to(obj);
    }
}

void  to_json(json& j, const ST_HPLC_MONITOR_REQMSG& msg)
{
    j = json{
        {"token",msg.token},
        {"timestamp",msg.timestamp },
        {"prio",msg.prio},
        {"acqAddr",msg.acqAddr},
        {"proType",msg.proType},
        {"overTime",msg.overTime},
        {"data",msg.data}
    };
}

void  from_json(const json& j, ST_HPLC_MONITOR_REQMSG& msg)
{
    j.at("token").get_to(msg.token);
    j.at("timestamp").get_to(msg.timestamp);
    j.at("prio").get_to(msg.prio);
    j.at("acqAddr").get_to(msg.acqAddr);
    j.at("proType").get_to(msg.proType);
    j.at("overTime").get_to(msg.overTime);
    j.at("data").get_to(msg.data);

}

void to_json(json& j, const ST_HPLC_MONITOR_RSPMSG& msg)
{
    j = json{
        { "token", msg.token },
        { "timestamp", msg.timestamp },
        { "proType", msg.proType },
        { "data", msg.data }
    };
}

void from_json(const json& j, ST_HPLC_MONITOR_RSPMSG& msg)
{
    j.at("token").get_to(msg.token);
    j.at("timestamp").get_to(msg.timestamp);
    j.at("proType").get_to(msg.proType);
    j.at("data").get_to(msg.data);
}


void to_json(json& j, const ST_DEV_ARCHIVES& msg)
{
    j = json{
        {"acqAddr",msg.acqAddr},
        {"proType",msg.proType}
    };
}
void from_json(const json& j, ST_DEV_ARCHIVES& msg)
{
    j.at("acqAddr").get_to(msg.acqAddr);
    j.at("proType").get_to(msg.proType);
}

void to_json(json& j, const std::list<ST_DEV_ARCHIVES>& objs)
{
    for (auto dev = objs.begin(); dev != objs.end();dev++)
    {
        j.push_back(*dev);
    }
}

void from_json(const json& j, std::list<ST_DEV_ARCHIVES>& objs)
{
    for (auto js = j.begin(); js != j.end();js++)
    {
        ST_DEV_ARCHIVES dev = *js;
        objs.push_back(dev);
    }
}

void to_json(json& j, const ST_HPLC_DEVARCHIVES_MSG& msg)
{
    j = {
        {"token", msg.token },
        {"timestamp", msg.timestamp },
        {"prio", msg.prio },
        {"body", msg.lstArchives}
    };
}

void from_json(const json& j, ST_HPLC_DEVARCHIVES_MSG& msg)
{
    json_to_obj<std::string>(j,"token",msg.token);
    json_to_obj<std::string>(j, "timestamp", msg.timestamp);
    json_to_obj<std::string>(j, "prio", msg.prio);
    json_to_obj<std::list<ST_DEV_ARCHIVES>>(j, "body", msg.lstArchives);
}

void  to_json(json& j, const ST_HPLC_CLEARARCHIVES_MSG& msg)
{
    j = {
        {"token", msg.token },
        {"timestamp", msg.timestamp },
        {"prio", msg.prio }
    };
}

void  from_json(const json& j, ST_HPLC_CLEARARCHIVES_MSG& msg)
{
    json_to_obj<std::string>(j, "token", msg.token);
    json_to_obj<std::string>(j, "timestamp", msg.timestamp);
    json_to_obj<std::string>(j, "prio", msg.prio);
}

void to_json(json& j, const ST_HPLC_COMM_RSPMSG& msg)
{
    j = {
        { "token", msg.token },
        { "timestamp", msg.timestamp },
        { "status", msg.status },
        { "reason", msg.reason }
    };
}

void from_json(const json& j, ST_HPLC_COMM_RSPMSG& msg)
{
    json_to_obj<std::string>(j, "token", msg.token);
    json_to_obj<std::string>(j, "timestamp", msg.timestamp);
    json_to_obj<std::string>(j, "status", msg.status);
    json_to_obj<std::string>(j, "reason", msg.reason);
}

void to_json(json& j, const ST_HPLC_ACQ_REQMSG& msg)
{
    j = {
        { "token", msg.token },
        { "timestamp", msg.timestamp },
        { "prio", msg.prio },
        { "acqAddr", msg.acqAddr },
        { "proType", msg.proType },
        {"data",msg.data}
    };
}

void from_json(const json& j, ST_HPLC_ACQ_REQMSG& msg)
{
    json_to_obj<std::string>(j, "token", msg.token);
    json_to_obj<std::string>(j, "timestamp", msg.timestamp);
    json_to_obj<std::string>(j, "prio", msg.prio);
    json_to_obj<std::string>(j, "acqAddr", msg.acqAddr);
    json_to_obj<std::string>(j, "proType", msg.proType);
    json_to_obj<std::string>(j, "data", msg.data);
}

void to_json(json& j, const ST_HPLC_DATAREPORT_RSPMSG& msg)
{
    j = {
        { "token", msg.token },
        { "timestamp", msg.timestamp },
        { "acqAddr", msg.acqAddr },
        { "proType", msg.proType },
        { "data", msg.data }
    };
}

void from_json(const json& j, ST_HPLC_DATAREPORT_RSPMSG& msg)
{
    json_to_obj<std::string>(j, "token", msg.token);
    json_to_obj<std::string>(j, "timestamp", msg.timestamp);
    json_to_obj<std::string>(j, "acqAddr", msg.acqAddr);
    json_to_obj<std::string>(j, "proType", msg.proType);
    json_to_obj<std::string>(j, "data", msg.data);
}

void to_json(json& j, const ST_HPLC_FREQPT_REQMSG& msg)
{
    j = {
        { "token", msg.token },
        { "timestamp", msg.timestamp },
        { "prio", msg.prio },
        { "hplcFreq", msg.freqPt }
    };
}

void from_json(const json& j, ST_HPLC_FREQPT_REQMSG& msg)
{
    json_to_obj<std::string>(j, "token", msg.token);
    json_to_obj<std::string>(j, "timestamp", msg.timestamp);
    json_to_obj<std::string>(j, "prio", msg.prio);
    json_to_obj<std::string>(j, "hplcFreq", msg.freqPt);
}

HPLCPacketManager::HPLCPacketManager()
{
}


HPLCPacketManager::~HPLCPacketManager()
{
}

int HPLCPacketManager::get_hplc_monitor_reqmsg(int64_t req_id, const std::string&  salveAddr, uint8_t *sendBuf, int buf_len, std::string &msg)
{
    int tl = get_base64_len(buf_len) + 100;
    char targetBuf[tl] = { 0 };
    tl = base64_encode((char*)sendBuf, buf_len, targetBuf, tl);

    ST_HPLC_MONITOR_REQMSG reqMsg;

    reqMsg.token = std::to_string(req_id);
    reqMsg.acqAddr = salveAddr;   //ToDo:У׼��ַ��Ч�ԣ�
    reqMsg.prio = "0";
    reqMsg.proType = "02";        //DL/T645-2007
    reqMsg.overTime = "5";        //��ʱʱ�䣬Ĭ��3S
    reqMsg.data = targetBuf;
    get_uart_timestamp(reqMsg.timestamp);

    json j = reqMsg;
    msg = j.dump();

    return msg.length();
}

int HPLCPacketManager::get_hplc_monitor_rspdata(const std::string &msg, char *recvBuf, int &recvBuf_len, std::string& token)
{
    if ((NULL == recvBuf) || (msg.empty())){
        recvBuf_len = -1;
        return -1;
    }

    
    auto j = json::parse(msg);
    //token
    if (!j.contains("token")){
        recvBuf_len = -1;
        token = "";
        CLogger::getInstance()->log_w("get_hplc_monitor_rspdata not contains token field.");
        return -1;
    }
    token = j["token"].get<std::string>();

    //data
    if (!j.contains("data")){
        recvBuf_len = -1;
        
        CLogger::getInstance()->log_i("get_hplc_monitor_rspdata not contains data field.");
        return -1;
    }

    std::string data = j["data"].get<std::string>();
    if ( data.empty()){ // || (recvBuf_len < (int)(data.length() / 2 + 1))){    //ToDo:���س����ж�?
        recvBuf_len = -1;
        CLogger::getInstance()->log_i("get_hplc_monitor_rspdata data field is null.");
        return -1;
    }
    CLogger::getInstance()->log_d("get_hplc_monitor_rspdata data field =%s.",data.c_str());

    int ret = base64_decode((char *)data.c_str(), data.length(), recvBuf, recvBuf_len);
    if (1 > ret){
        recvBuf_len = -1;
        return -1;
    }
    recvBuf_len = ret;

    return recvBuf_len;
}

int HPLCPacketManager::get_hplc_addarchives_reqmsg(int64_t req_id, std::list<ST_DEV_ARCHIVES>& lstarchives, std::string &msg)
{
    ST_HPLC_DEVARCHIVES_MSG stAddArchivesMsg;

    stAddArchivesMsg.token = std::to_string(req_id);
    stAddArchivesMsg.prio = "0";
    for (auto devarch = lstarchives.begin(); devarch != lstarchives.end(); devarch++)
    {
        stAddArchivesMsg.lstArchives.push_back(*devarch);
    }
    get_uart_timestamp(stAddArchivesMsg.timestamp);

    json j = stAddArchivesMsg;
    msg = j.dump();

    return  msg.length();
}

int HPLCPacketManager::get_hplc_cleararchives_reqmsg(int64_t req_id, std::string &msg)
{
    ST_HPLC_CLEARARCHIVES_MSG  stClearMsg;

    stClearMsg.token = std::to_string(req_id);
    stClearMsg.prio = "0";
    get_uart_timestamp(stClearMsg.timestamp);

    json j = stClearMsg;
    msg = j.dump();

    return msg.length();
}

int HPLCPacketManager::get_hplc_comm_rspdata(const std::string &msg, std::string& status)
{
    if (msg.empty())
    {
        return -1;
    }

    //status
    auto j = json::parse(msg);
    if (!j.contains("status")){
        return -1;
    }
    
    status = j["status"].get<std::string>();
    
    return status.length();
}

int HPLCPacketManager::get_hplc_acqdata_reqmsg(int64_t req_id, const std::string& salveAddr, char* sendbuf, int buflen, std::string& msg)
{
    int tl = get_base64_len(buflen) + 100;
    char targetBuf[tl] = { 0 };
    tl = base64_encode(sendbuf, buflen, targetBuf, tl);

    ST_HPLC_ACQ_REQMSG reqMsg;

    reqMsg.token = std::to_string(req_id);
    reqMsg.acqAddr = salveAddr;   
    reqMsg.prio = "0";
    reqMsg.proType = "02";        //DL/T645-2007
    reqMsg.data = targetBuf;
    get_uart_timestamp(reqMsg.timestamp);

    json j = reqMsg;
    msg = j.dump();

    return msg.length();
}

int HPLCPacketManager::get_hplc_acqdata_rspmsg(const std::string &msg, std::string& slaveAddr, char *recvBuf, int &recvBuf_len)
{
    if ((NULL == recvBuf) || (msg.empty())){
        recvBuf_len = -1;
        return -1;
    }
       
    auto j = json::parse(msg);
    if (nullptr == j["data"]){
        recvBuf_len = -1;
        return -2;
    }

    //slaveAddr
    slaveAddr = j["acqAddr"].get<std::string>();
    if (slaveAddr.empty())
    {
        recvBuf_len = -1;
        return -3;
    }

    //data
    std::string data = j["data"].get<std::string>();
    if (data.empty()){ 
        recvBuf_len = -1;
        return -4;
    }
    int ret = base64_decode((char *)data.c_str(), data.length(), recvBuf, recvBuf_len);
    if (1 > ret){
        recvBuf_len = -1;
        return -5;
    } else {
        recvBuf_len = ret;
    }

    return recvBuf_len;
}

int HPLCPacketManager::get_hplc_freqset_reqmsg(int64_t req_id, int freqPt, std::string &msg)
{
    ST_HPLC_FREQPT_REQMSG  stFrqMsg;

    stFrqMsg.token = std::to_string(req_id);
    stFrqMsg.prio = "0";
    stFrqMsg.freqPt = std::to_string(freqPt);
    get_uart_timestamp(stFrqMsg.timestamp);

    json j = stFrqMsg;
    msg = j.dump();

    return msg.length();
}
